/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.muni.fi.j002.requirementengineeringmuni.impl;

import cz.muni.fi.j002.requirementengineeringmuni.Deck;
import cz.muni.fi.j002.requirementengineeringmuni.Game;
import cz.muni.fi.j002.requirementengineeringmuni.Player;
import cz.muni.fi.j002.requirementengineeringmuni.entities.Move;
import cz.muni.fi.j002.requirementengineeringmuni.util.RuleEngine;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 *
 * @author stefan
 */
public class GameImpl implements Game {
    
    private boolean gameFinished;
    
    private Player firstPlayer;
    private Player secondPlayer;
    
    private BigDecimal firstPlayerScore = BigDecimal.ZERO;
    private BigDecimal secondPlayerScore = BigDecimal.ZERO;
    
    private List<Move> playedMoves = new ArrayList<Move>();
    
    private Deck deck = new DeckImpl();
    
    public GameImpl(Player firstPlayer, Player secondPlayer) {
        this.firstPlayer = firstPlayer;
        this.secondPlayer = secondPlayer;
    }

    @Override
    public BigDecimal getFirstPlayerScore() {
        return firstPlayerScore;
    }

    @Override
    public BigDecimal getSecondPlayerScore() {
        return secondPlayerScore;
    }

    @Override
    public Player getFirstPlayer() {
        return firstPlayer;
    }

    @Override
    public Player getSecondPlayer() {
        return secondPlayer;
    }
    
    @Override
    public Deck getDeck() {
        return deck;
    }

    @Override
    public void addAndEvaluateNewMove(Move newMove) {
        if(gameFinished) throw new IllegalStateException("game already finished");
        
        if(getLastPlayedMove() != null) {
            this.firstPlayerScore = this.firstPlayerScore.add(RuleEngine.getFirstPlayerBetResult(getLastPlayedMove(), newMove));
            this.secondPlayerScore = this.secondPlayerScore.add(RuleEngine.getSecondPlayerBetResult(getLastPlayedMove(), newMove));
        }
        
        this.playedMoves.add(newMove);
    }

    @Override
    public List<Move> getPlayedMoves() {
        return Collections.unmodifiableList(playedMoves);
    }

    @Override
    public Move getLastPlayedMove() {
        if(playedMoves.isEmpty()) return null;
        return playedMoves.get(playedMoves.size()-1);
    }

    @Override
    public Player getWinner() {
        switch (firstPlayerScore.compareTo(secondPlayerScore)) {
            case -1: return secondPlayer;
            case 0: return null;
            default: return firstPlayer;
        } 
    }
    
    @Override
    public void finishGame() {
        if(gameFinished) throw new IllegalStateException("game already finished");
        this.gameFinished = true;
    }

    @Override
    public boolean canFirstPlayerMakeABet(BigDecimal amount) {
        return 1 == amount.compareTo(firstPlayer.getBank().getAccountState().add(firstPlayerScore)) ? false : true;
    }

    @Override
    public boolean canSecondPlayerMakeABet(BigDecimal amount) {
        return 1 == amount.compareTo(secondPlayer.getBank().getAccountState().add(secondPlayerScore)) ? false : true;
    }
    
}
